import {
  HttpStatus,
  Module,
  UnprocessableEntityException,
} from '@nestjs/common';
import { FilesMinioController } from './files.controller';
import { MulterModule } from '@nestjs/platform-express';
import { ConfigModule, ConfigService } from '@nestjs/config';

import { FilesMinioService } from './files.service';
import { RelationalFilePersistenceModule } from '../../db/relational-persistence.module';
import { AllConfigType } from '../../../../config/config.type';
import { randomStringGenerator } from '@nestjs/common/utils/random-string-generator.util';
import {
  CreateBucketCommand,
  ListBucketsCommand,
  S3Client,
} from '@aws-sdk/client-s3';
import multerS3 from 'multer-s3';
import awaitTo from 'await-to-js';
import { createLogger } from '@/common/logger/common';
import { fileReg } from '@/config/common';
// import { LoggerService } from '@/common/logger/logger.service';
@Module({
  imports: [
    RelationalFilePersistenceModule,
    MulterModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService<AllConfigType>) => {
        // console.log(loggerService)
        const logger = createLogger('minio');
        const s3 = new S3Client({
          region: configService.get('file.awsS3Region', { infer: true }),
          endpoint: `http://${configService.get('file.endPoint', { infer: true })}:${configService.get('file.endPointPort', { infer: true })}`,
          forcePathStyle: true,
          credentials: {
            accessKeyId: configService.getOrThrow('file.accessKeyId', {
              infer: true,
            }),
            secretAccessKey: configService.getOrThrow('file.secretAccessKey', {
              infer: true,
            }),
          },
        });
        const [err, res] = await awaitTo(s3.send(new ListBucketsCommand({})));
        if (err) {
          logger.error(err, 'minio');
        }
        if (res) {
          const bucket = configService.getOrThrow('file.awsDefaultS3Bucket', {
            infer: true,
          });
          const target = res.Buckets?.find((e) => e.Name == bucket);
          if (!target) {
            logger.error(`bucket:${bucket}不存在，请检查minio`, 'minio');
            s3.send(new CreateBucketCommand({ Bucket: bucket }))
              .then(() => {
                logger.debug(`${bucket}不存在，已自动创建`, 'minio');
              })
              .catch((err) => {
                logger.error(err, 'minio');
              });
          }
        }
        return {
          fileFilter: (request, file, callback) => {
            console.log(file, fileReg, fileReg.test(file.originalname));
            if (!file.originalname.match(fileReg)) {
              return callback(
                new UnprocessableEntityException({
                  status: HttpStatus.UNPROCESSABLE_ENTITY,
                  errors: {
                    file: `cantUploadFileType`,
                  },
                }),
                false,
              );
            }

            callback(null, true);
          },
          storage: multerS3({
            s3: s3,
            bucket: configService.getOrThrow('file.awsDefaultS3Bucket', {
              infer: true,
            }),
            contentType: multerS3.AUTO_CONTENT_TYPE,
            key: (request, file, callback) => {
              callback(
                null,
                `${randomStringGenerator()}.${file.originalname
                  .split('.')
                  .pop()
                  ?.toLowerCase()}`,
              );
            },
          }),
          limits: {
            fileSize: configService.get('file.maxFileSize', { infer: true }),
          },
        };
      },
    }),
  ],
  controllers: [FilesMinioController],
  providers: [FilesMinioService],
  exports: [FilesMinioService],
})
export class FilesMinioModule {}
